package impl

import (
	"fmt"
	pb "gitee.com/micro-services/protocol/user/server"
	"log"
	"micro.user.auth.server/dao"
	"micro.user.auth.server/factory"
)

type tokenAction struct{}

func (*tokenAction) GenerateToken(userId uint64, platform string, key map[string]interface{}) (*pb.GenerateTokenRsp, error) {
	jwt, err := dao.GenerateToken(userId, key)
	if err != nil {
		return nil, err
	}

	return &pb.GenerateTokenRsp{
		Token: jwt,
	}, nil
}

func (*tokenAction) CheckToken(userId uint64, token string) (bool, error) {
	return dao.CheckToken(userId, token)
}

func (*tokenAction) ResolveToken(userId uint64, token string) (map[string]interface{}, error) {
	return dao.ResolveToken(userId, token)
}

func (*tokenAction) RefreshToken(userId uint64, token string) (*pb.GenerateTokenRsp, error) {
	jwt, err := dao.RefreshToken(userId, token)
	if err != nil {
		return nil, err
	}

	return &pb.GenerateTokenRsp{Token: jwt}, nil
}

type userRoleAction struct{}

func (*userRoleAction) CheckUserRole(userId uint64, token, urlPath string) (bool, error) {

	return false, nil
}

type wxUserAction struct {
	wxTokenKey string
}

func (w *wxUserAction) GetWxUserInfo(code string) (*pb.GetWxUserInfoRsp, error) {
	rsp, err := dao.GetWxUserInfo(code)
	if err != nil {
		return nil, err
	}

	return &pb.GetWxUserInfoRsp{
		OpenId:     rsp.Openid,
		SessionKey: rsp.SessionKey,
		UnionId:    rsp.UnionId,
	}, nil
}

func (w *wxUserAction) GetWxUserToken(platform string, userId uint64) (string, error) {
	// todo.设置缓存，如果命中则直接返回，否则再去获取 access token
	key := fmt.Sprintf(w.wxTokenKey, platform, userId)

	token, err := dao.GetWxAccessTokenFromRedis(key)
	if err != nil || token == "" {
		// 容错，遇到error时，从微信获取token
		log.Printf("GetWxAccessTokenFromRedis get token err:%+v, toke:%+v", err, token)
	}
	if token != "" {
		return token, nil
	}

	rsp, err := dao.GetWxAccessToken(key)
	if err != nil {
		return "", err
	}

	return rsp.AccessToken, nil
}

func BuilderGenerateToken() factory.TokenFactory {
	return &tokenAction{}
}

func BuilderWxUser() factory.WxUserFactory {
	return &wxUserAction{
		// platform_userId_token
		wxTokenKey: fmt.Sprintf("%s_%d_token"),
	}
}
